
#include "appXssl.h"
#include "polarssl/base64.h"

xsMsg_t     s_stMsg = {0};
xsPre_t     s_stPre = {0};
extern xsUserCfg_t s_stUserCfg;

extern unsigned int  g_uiTraffic; //Traffic statistics
extern unsigned int  g_uiMaxTraffic;
extern unsigned char g_ucXcStep;

xsMsg_t     s_stC2TMsg = {0};

extern  xsCtx_t      s_stxsCtx;
#if defined(XC_UDP)
extern  xsNatINfo_t stNatInfo;
#endif
static unsigned char s_aucComBuf[COM_MAX_BUF_SIZE] = {0};

unsigned int g_uiURtime = 0;
static unsigned char s_ucDevPeerStat = XS_JID_OFFLINE;
unsigned char g_ucPreStat = XS_PRE_NORMAL;
unsigned char g_ucCmdStat = XS_PRE_NORMAL;

void comm_uart1_cfg(xsUserCfg_t *pstUserCfg);

int proxy_comm_proc(void)
{
  int iRet = S_OK;
  unsigned int   uiRLen = 0, uiSLen = 0;
  static unsigned char s_ucC2Tok = SWITCH_OFF;

  if(0 == s_stUserCfg.acDevPeer[0]){
    g_ucPreStat = XS_NO_CFG;
  }
  
  if(0 != s_stUserCfg.acDevJID[0]){
   do{
  		iRet = uart1_recv_data(s_aucComBuf+uiRLen, COM_MAX_BUF_SIZE-uiRLen);
  	  if(0 < iRet){
  			uiRLen += iRet;
  			if(0 == g_uiURtime){
  				g_uiURtime = 100; /*read value*1ms*/
  			}else{
  				continue;
  			}
  	 	}
  	}while(g_uiURtime);
    
  	if(0 < uiRLen){
      print_log(D_INFO, ("Cin:%d\n", uiRLen));
      #if 0
  		if(DBG_ON == g_ucDebug){
  			print_log(D_DEBUG, ("C->T[%d][", uiRLen));
  			for(i=0; i<uiRLen; i++){
  				print_log(D_DEBUG, ("%02X", s_aucComBuf[i]));
  			}
  			print_log(D_DEBUG, ("]\n"));
  		}
      #endif
      memset(s_stC2TMsg.aucMsgData, 0, XS_MAX_MSG_SIZE);
      if(DATA_FORMAT_ASCII != s_stUserCfg.ucDataFormat){
    		s_stC2TMsg.uiMsgLen = XS_MAX_MSG_SIZE;
    		iRet = base64_encode(s_stC2TMsg.aucMsgData, &s_stC2TMsg.uiMsgLen, s_aucComBuf, uiRLen);
      }else{
        memcpy(s_stC2TMsg.aucMsgData, s_aucComBuf, uiRLen);
        s_stC2TMsg.uiMsgLen = uiRLen;
        iRet = 0;
      }
      if(0 == iRet){
        memcpy(s_stC2TMsg.aucJid, s_stUserCfg.acDevJID, strlen(s_stUserCfg.acDevJID));
        s_ucC2Tok = SWITCH_ON;
      }else{
        uiRLen = 0;
      }
  	}
    
    if(SWITCH_ON == s_ucC2Tok){
      iRet = xsXmppSendMsg(&s_stxsCtx, &s_stC2TMsg);
      if(XS_OK == iRet){
        s_ucC2Tok = SWITCH_OFF;
        print_log(D_INFO, ("Tout:[%s] %d\n", s_stC2TMsg.aucJid, s_stC2TMsg.uiMsgLen));
        memset(&s_stC2TMsg, 0, sizeof(xsMsg_t));
      }
    }
  }

  iRet = xsXmppConnProc(&s_stxsCtx, &s_stMsg, &s_stPre, &s_stUserCfg);

  if(XS_DATA == s_stMsg.ucFlag){
    uiRLen = sizeof(s_aucComBuf);
    if(DATA_FORMAT_ASCII != s_stUserCfg.ucDataFormat){
      iRet = base64_decode(s_aucComBuf, &uiRLen, s_stMsg.aucMsgData, s_stMsg.uiMsgLen);
    }else{
      memcpy(s_aucComBuf, s_stMsg.aucMsgData, s_stMsg.uiMsgLen);
      uiRLen = s_stMsg.uiMsgLen;
      iRet = 0;
    }
    if(0 == iRet){
      print_log(D_INFO, ("Tin:[%s] %d\n", s_stMsg.aucJid, s_stMsg.uiMsgLen));
      uiSLen = 0;
  		do{
  			iRet = uart1_send_data(s_aucComBuf+uiSLen, uiRLen-uiSLen);
  			uiSLen += iRet;
  		}while(uiSLen < uiRLen);
      print_log(D_INFO, ("Cout:%d\n", uiSLen));
      #if 0
  		if(DBG_ON == g_ucDebug){
  			print_log(D_DEBUG, ("T->C[%d][", uiRLen));
  			for(i=0; i<uiRLen; i++){
  				print_log(D_DEBUG, ("%02X", s_aucComBuf[i]));
  			}
  			print_log(D_DEBUG, ("]\n"));
  		}
      #endif
    }else{
      g_ucPreStat = XS_DATA_ERR;
    }
    memset(&s_stMsg, 0, sizeof(xsMsg_t));
	}

  if(XS_PRE_STATE == s_stPre.ucFlag && 0 != s_stUserCfg.acDevPeer[0]){
    if(0 != strstr((char *)s_stPre.aucJid, s_stUserCfg.acDevPeer) && 0 != strstr((char *)s_stPre.aucStatType, "unavailable")){
      s_ucDevPeerStat = XS_JID_OFFLINE;
      print_log(D_INFO, ("Peer ID:%s offline\n", s_stUserCfg.acDevPeer));
    }else if(0 != strstr((char *)s_stPre.aucJid, s_stUserCfg.acDevPeer)){
      s_ucDevPeerStat = XS_JID_ONLINE;
      print_log(D_INFO, ("Peer ID:%s online\n", s_stUserCfg.acDevPeer));
    }
    
  }else if(XS_PRE_CMD == s_stPre.ucFlag){
    print_log(D_INFO, ("User cmd :%d value:%s\n", s_stUserCfg.ucCmd, s_stUserCfg.aucCmdValue));
    if(0xFF != s_stUserCfg.ucCmd){    
      g_ucCmdStat = XS_PRE_NORMAL;
      switch(s_stUserCfg.ucCmd){
        case XS_SET_CFG:
          print_log(D_INFO, ("User set new cfg \n"));
          iRet = user_cfg_write(WRITE_CFG_INFO);
          if(0 != iRet){
            g_ucPreStat = XS_WFLASH_ERR;
          }
          iRet = user_cfg_read();
          if(0 != iRet){
            g_ucPreStat = XS_NO_CFG;
          }else{
            comm_uart1_cfg(&s_stUserCfg);
            g_ucPreStat = XS_PRE_NORMAL;
          }
          break;
        case XS_SET_TRAFFIC:
          g_uiTraffic = 0;
          g_uiMaxTraffic = atoi((char *)s_stUserCfg.aucCmdValue);
          traffic_statistics_write();
          break;
        case XS_CMD_TEST:
          iRet = atoi((char *)s_stUserCfg.aucCmdValue);
          if(0 < iRet && 3 > iRet)
          buzzer_ring(iRet);
          iRet = 0;
          break;
        default :
          g_ucCmdStat = 1;
          break;
      }
      g_ucXcStep = P_CMD_RES;
    }
  }
  if(0 != s_stPre.ucFlag){
    memset(&s_stPre, 0, sizeof(xsPre_t));
  }
  return iRet;
}

int p2p_comm_proc(void)
{
  int iRet = S_OK;

  return iRet;
}

void comm_uart1_cfg(xsUserCfg_t *pstUserCfg)
{
  uint32_t uiBaudRate;
  uint16_t usWordLength,
           usStopBits,
           usParity,
           usCtx;

  if(0 < pstUserCfg->stCom.baudrate){
    uiBaudRate = pstUserCfg->stCom.baudrate;
  }else{
    return;
  }
  switch(pstUserCfg->stCom.databit){
    case 8:
      usWordLength = USART_WordLength_8b;
      break;
    case 9:
      usWordLength = USART_WordLength_9b;
      break;
    default:
      usWordLength = USART_WordLength_8b;
      break;
  }

  switch(pstUserCfg->stCom.stopbit){
    case 0:
      usStopBits = USART_StopBits_0_5;
      break;
    case 1:
      usStopBits = USART_StopBits_1;
      break;
    case 3:
      usStopBits = USART_StopBits_1_5;
      break;
    case 2:
      usStopBits = USART_StopBits_2;
      break;
    default:
      usStopBits = USART_StopBits_1;
      break;
  }

  switch(pstUserCfg->stCom.parity){
    case 0:
      usParity = USART_Parity_No;
      break;
    case 1:
      usParity = USART_Parity_Even;
      break;
    case 2:
      usParity = USART_Parity_Odd;
      break;
    default:
      usParity = USART_Parity_No;
      break;
  }

  switch(pstUserCfg->stCom.flowctrl){
    case 0:
      usCtx = USART_HardwareFlowControl_None;
      break;
    case 1:
      usCtx = USART_HardwareFlowControl_RTS;
      break;
    case 2:
      usCtx = USART_HardwareFlowControl_CTS;
      break;
    case 3:
      usCtx = USART_HardwareFlowControl_RTS_CTS;
      break;
    default:
      usCtx = USART_HardwareFlowControl_None;
      break;
  }
  
  uart1_init(uiBaudRate, usWordLength, usStopBits, usParity, usCtx);
}

void comm_release(void)
{
  s_ucDevPeerStat = XS_JID_OFFLINE;
  g_ucPreStat = XS_PRE_NORMAL;
  g_uiURtime = 0;
  traffic_statistics_write();
}

